package com.mhkj.revise.mainPlan.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.mhkj.revise.mainPlan.repository.MainPlanNodeRepository;
import com.mhkj.revise.mainPlan.service.MainPlanNodeService;
import com.mhkj.revise.mainPlan.service.MainPlanService;
import com.mhkj.revise.plan.entity.Plan;
import com.mhkj.revise.plan.entity.PlanNode;
import com.mics.core.common.componet.Pagination;
import com.mics.core.common.util.DateUtils;
import com.mics.core.system.base.service.impl.BaseServiceImpl;
import com.mics.core.system.organizational.bean.Company;
import com.mics.core.system.organizational.bean.Office;
import com.mics.core.system.organizational.bean.Post;
import com.mics.core.system.organizational.service.OrgService;

/**
 * 主项计划节点
 * @author mics
 * @date 2018年8月18日
 * @version 1.0
 */
@Service
public class MainPlanNodeServiceImpl extends BaseServiceImpl<PlanNode> implements MainPlanNodeService{
	@Resource
	private MainPlanNodeRepository mainPlanNodeRepository;
	@Resource
	private MainPlanService mainPlanService;
	@Resource
	private OrgService orgService;
	
	@Resource
	public void setMainPlanNodeRepository(
			MainPlanNodeRepository mainPlanNodeRepository) {
		super.setBaseRepository(mainPlanNodeRepository);
	}

	/**
	 * 推算周期准备
	 */
	@Override
	@Transactional
	public void calsDealinePrepare(long planId) {
		//寻找初始节点
		Plan plan = mainPlanService.getById(planId);
		List<PlanNode> planNodes = mainPlanNodeRepository.getPlanNodeByPlanId(planId);
		//推算周期
		calsDealine(planNodes);
		//寻找完成时间最大得节点
		PlanNode lastPlanNode = mainPlanNodeRepository.getLastPlanNode(planId);
		plan.setEndDate(lastPlanNode.getEndDate());
		//寻找完成时间最小得节点
		PlanNode fristPlanNode = mainPlanNodeRepository.getFristPlanNode(planId);
		plan.setEndDate(lastPlanNode.getEndDate());
		plan.setBeginDate(fristPlanNode.getBeginDate());
		mainPlanService.edit(plan);
	}
	
	
	
	/**
	 * 推算周期
	 * @author mics
	 * @date 2018年8月14日
	 * @version 1.0
	 */
	private void calsDealine(List<PlanNode> planNodes) {
		for(PlanNode planNode:planNodes){
			if(planNode.getBeginDate() == null){
				copyFromUpName(planNode,planNode.getPlan().getPlan()); //复制上级同名节点时间
			}
		}    
		for(PlanNode planNode:planNodes){
			if(planNode.getBeginDate() == null){
				searchOtherNodes(planNode,planNode.getPlan().getPlan()); //从上级节点搜索推算
			}
		}    
		List<PlanNode> failNodes = new ArrayList<PlanNode>();
		for(PlanNode planNode:planNodes){
			if(planNode.getBeginDate() == null){
				PlanNode planNodeFail = searchOtherNodes(planNode,planNode.getPlan()); //到当前搜索节点推算
				if(planNodeFail != null){
					failNodes.add(planNodeFail);
				}
			}
		}  
		retryCurrent(failNodes,1); //重新尝试当前级别寻找
	}
	
	/**
	 * 搜索上级节点
	 * @author mics
	 * @date 2018年8月28日
	 * @version 1.0
	 */
	private void copyFromUpName(PlanNode planNode,Plan plan) {
		List<PlanNode> keyPlanNodes = plan.getPlanNodes();
		for(PlanNode planNodeTemp : keyPlanNodes){
			if(planNode.getNodeName().equals(planNodeTemp.getNodeName())){
				planNode.setBeginDate(planNodeTemp.getBeginDate());
				planNode.setEndDate(planNodeTemp.getEndDate());
				edit(planNode);
			}
		}
	}
	
	
	/**
	 * 重试当前失败节点
	 * @author mics
	 * @date 2018年8月28日
	 * @version 1.0
	 */
	private void retryCurrent(List<PlanNode> planNodeFails,int count){
		List<PlanNode> planNodeFailsNew = new ArrayList<PlanNode>();
		for(PlanNode planNode:planNodeFails){
			if(planNode.getBeginDate() == null){
				PlanNode planNodeFail = searchOtherNodes(planNode,planNode.getPlan()); //到当前搜索节点
				if(planNodeFail != null){
					planNodeFailsNew.add(planNodeFail);
				}
			}
		}
		if(planNodeFailsNew.size() > 0){
			count++;
			if(count< 100){
				retryCurrent(planNodeFailsNew,count);
			}
		}
	}
	
	/**
	 * 搜索节点推算
	 * @author mics
	 * @date 2018年8月28日
	 * @version 1.0
	 */
	private PlanNode searchOtherNodes(PlanNode planNode,Plan plan) {
		List<PlanNode> keyPlanNodes = plan.getPlanNodes();
		for(PlanNode planNodeTemp : keyPlanNodes){
			String deadlineDes = planNode.getDeadlineDesc();
			String[] array = deadlineDes.split("\\|");
			String nameGet = array[0];
			int deadl = Integer.valueOf(array[1]);
			String condition = array[2];
			if(planNodeTemp.getNodeName().equals(nameGet)){
				if(planNodeTemp.getBeginDate() != null){
					if(condition.equals("之后")){
						Date beginDate = DateUtils.addDay(planNodeTemp.getEndDate(),deadl);
						planNode.setBeginDate(beginDate);
						planNode.setEndDate(DateUtils.addDay(beginDate, planNode.getDeadline()));
					}else if(condition.equals("之内")){ 
						Date beginDate = DateUtils.subDay(DateUtils.addDay(planNodeTemp.getEndDate(), deadl),planNodeTemp.getDeadline());
						planNode.setBeginDate(beginDate);
						planNode.setEndDate(DateUtils.addDay(beginDate, planNode.getDeadline()));
					}else if(condition.equals("之前")){
						Date date = DateUtils.subDay(planNodeTemp.getBeginDate(), deadl);
						planNode.setBeginDate(date);
						planNode.setEndDate(DateUtils.addDay(date, planNode.getDeadline()));
					}
					edit(planNode);
				}else{
					return planNode;
				}
				
			}
		}
		return null;
	}
	
	


	

	@Override
	public Pagination<PlanNode> listByPage(PlanNode planNode, int pageIndex,int pageSize) {
		Specification<PlanNode> spec = new Specification<PlanNode> () {  
			private static final long serialVersionUID = -786003485941679959L;
			@Override
			public Predicate toPredicate(Root<PlanNode> root, CriteriaQuery<?> query,
					CriteriaBuilder criteriaBuilder) {
              List<Predicate> lstPredicates = new ArrayList<Predicate>();
              if(!StringUtils.isEmpty(planNode.getNodeName())){
                  Predicate p1=criteriaBuilder.like(root.get("name").as(String.class), "%"+planNode.getNodeName()+"%");
                  lstPredicates.add(p1);
              }
              if(planNode.getPlan() != null){
                  Join<Object, Object> plan = root.join("plan",JoinType.INNER);
                  Predicate p1=criteriaBuilder.equal(plan.get("id").as(Long.class), planNode.getPlan().getId());
                  lstPredicates.add(p1);
              }
              Predicate[] arrayPredicates = new Predicate[lstPredicates.size() ];
              return criteriaBuilder.and(lstPredicates.toArray(arrayPredicates));
	        }
		};
		Page<PlanNode> pageT =  mainPlanNodeRepository.findAll(spec, PageRequest.of(pageIndex, pageSize, Sort.Direction.ASC,"id"));
		Pagination<PlanNode> pagination = new Pagination<PlanNode>();
		pagination.setTotal(mainPlanNodeRepository.count(spec));
		List<PlanNode> plans = pageT.getContent();
		for(PlanNode planNode2 : plans){
			Company company = orgService.getCompanyById(planNode2.getCompanyId());
			planNode2.setCompanyName(company.getCompanyname());
			Office cOffice = orgService.officeInfo(planNode2.getOfficeId());
			planNode2.setOfficeName(cOffice.getName());
			Post post = orgService.getRoleInfo(planNode2.getPostId());
			planNode2.setPostName(post.getName());
		}
		pagination.setData(plans);
		return pagination;
	}



}
